home *** CD-ROM | disk | FTP | other *** search
/ NetNews Offline 2 / NetNews Offline Volume 2.iso / news / comp / sys / amiga / programmer / 6885 < prev    next >
Encoding:
Internet Message Format  |  1996-08-05  |  6.6 KB

  1. Subject: Re: Collision Detects !!!!
  2. References: <199603311357.NAA27594@mailhost.unibol.com>
  3. X-Newsreader: TIN [version 1.2 PL2]
  4. Path: imada.ou.dk!breese
  5. From: breese@imada.ou.dk (Bjorn Reese)
  6. Message-ID: <1996Apr4.112435.19268@imada.ou.dk>
  7. Sender: news@imada.ou.dk
  8. Nntp-Posting-Host: wagner.imada.ou.dk
  9. Organization: Dept. of Math. & Computer Science, Odense University, Denmark
  10. Date: Thu, 4 Apr 1996 11:24:35 GMT
  11. Newsgroups: comp.sys.amiga.programmer
  12.  
  13. John Girvin (jgirvin@bfs.unibol.com) wrote:
  14.  
  15. > px2 = player->x + player->width        // PreCalc player BRHC coords.
  16. > py2 = player->y + player->height
  17. >
  18. > for (i=1; i<num_bullets; i++)
  19. > {
  20. >     if ( (bullet[i]->x - px2) < (bullet[i]->width + player->width) &&
  21. >          (bullet[i]->y - py2) < (bullet[i]->height + player->height) )
  22.  
  23. I might be missing something, but it seems to me that this only works
  24. under the assumption that the bullets are to the right and above the
  25. player (ie. bullet[i]->x < player->x and similar for y.) Furthermore,
  26. as player->width is present on both sides of the inequality it can be
  27. omitted.
  28.  
  29. > A not-so-obvious optimisation depends on the shape of your playing
  30. > area. If its tall and thin (eg: vertical scroller) then it is more
  31. > likely that the Y-coords will be "out of range" than the X coords,
  32. > so you should shift the Y comparison to be first in order to be more
  33. > likely to discard non-collisions on the first comparison. Vice-versa
  34. > if your playing area is wider than it is tall.
  35.  
  36. Yes, this is a nice optimisation technique which also may be applied
  37. to programming in general. For instance if you have to do different
  38. things if a value is positive, negative, or zero, it may be a good
  39. idea to check for the positive case first if that is most likely to
  40. happen.
  41.  
  42. Optimizing collision detection is strongly dependent on the
  43. environment in which it takes place and the number of entities to
  44. check.
  45.  
  46. The simple "check all ordered pair of entities" approach will
  47. always win over more sophisticated approaches if the number of
  48. entities are small (without specifying how small "small" is.)
  49.  
  50. With specific knowledge of the environment in which to do the
  51. collision detection must take place, there are specific tricks
  52. that you can utilize. One that immediately springs to mind is if
  53. you have a horizontal scrolling game (same applies to vertical
  54. scrolling) you can keep all entities in a list sorted by the
  55. x-coordinate. Instead of checking for collision with all other
  56. entities, it is sufficient to check with those within range.
  57.  
  58. > Also, look for references on "sector based collision detection",
  59. > especially around rec.games.programmer archives (HINT!). It might
  60. > help you more if you have lots of objects to check.
  61.  
  62. I never really liked this idea of subsections for two reasons.
  63.  
  64.   (1) Problems with boundaries. To solve this you have to check
  65.       the neighbouring subsections as well.
  66.  
  67.   (2) Static segmentation. Choosing many small subsections may
  68.       require too much management of their lists (or arrays) as
  69.       the entities moves around. Choosing fewer bigger subsection
  70.       will gain nothing if most entities are clustered in the
  71.       adjacent subsection (which they often are.)
  72.  
  73. Subsections (static partitioning) can be sketched by this
  74.  
  75.   for previous, current & next y-subsection
  76.     for previous, current & next x-subsection
  77.       CheckCollision
  78.  
  79. Add to this the cost of maintaining the entities in the subsections.
  80.  
  81.  
  82. I personally prefer a dynamic partitioning. This is an extension of
  83. the horizontal scrolling trick mentioned earlier in this letter.
  84.  
  85. What you do is maintain two linked lists; one with all entities sorted
  86. by their x-coordinate, and one by their y-coordinate. It isn't necessary
  87. to sort the entire lists each frame. As the entities only move relatively
  88. short distances you can just "bobble" the entities into their correct
  89. position (ie. let them switch position in the linked list if their
  90. keys - the x and y coordinates respectively - demands this.)
  91.  
  92. Okay, now that we've got the two ordered lists, it is sufficient to check
  93. for collision with the entities that are within range by transversing
  94. through the lists. Once we get to an entity that is out of range we can
  95. discard the rest of the list (in one direction as we have to check each
  96. list in both directions from the current entity.)
  97.  
  98. This, however, can be further "cooked down" if the collision handling
  99. is expensive in itself. Currently we check a "band" on both the x and
  100. y axis (the x's, y's and the O in the figure below) although we only
  101. need to check the intersection of these two bands (the O.) To do this
  102. we just mark entities as potential check when we run through the x
  103. list, and do the collision handling when we run through the y list
  104. if they were mark in the previous run.
  105.  
  106.     +------+-+----+
  107.     |      |y|    |
  108.     |      |y|    |
  109.     +------+-+----+
  110.     |xxxxxx|O|xxxx|
  111.     +------+-+----+
  112.     |      |y|    |
  113.     +------+-+----+
  114.  
  115.  
  116. So what you need to do is the following
  117.  
  118.   while (|dx| > dx0) do
  119.     mark agent
  120.   while (|dy| > dy0) do
  121.     if (agent is marked) then HandleCollision
  122.  
  123. Furthermore there is the cost of maintaining the two ordered list, plus
  124. the set used for marking.
  125.  
  126. The (untested) code below works under the assumption that there is a
  127. known maximum number of entities (SETSIZE), and that each entities has
  128. a unique ID number (from [0,SETSIZE-1].) Furthermore, the maximum width
  129. and height of the entities must be known (XSIZEMAX and YSIZEMAX.) An
  130. entity is called an agent.
  131.  
  132.  
  133. typedef struct Agent {
  134.   /* ... whatever ... */
  135.   int xpos, ypos;
  136.   int xsize, ysize;
  137.   int id;
  138.   struct Agent *xnext;
  139.   struct Agent *xprev;
  140.   struct Agent *ynext;
  141.   struct Agent *yprev;
  142. } agent;
  143.  
  144.  
  145. /* for each agent call Collide() */
  146.  
  147. void Collide(agent *p)
  148. {
  149.   static unsigned int scnt = 0;
  150.   static unsigned int set[SETSIZE];
  151.   agent *s;
  152.   int t;
  153.  
  154.   if (scnt++ == 0) memset(&set, '\0', SETSIZE);
  155.  
  156.   t = p->xpos + p->xsize + XSIZEMAX;
  157.   for (s = p->xnext; s && (s->xpos < t); s = s->xnext)
  158.     /* --- Mark s->id as member of set --- */
  159.     set[s->id] = scnt;
  160.   t = p->xpos - (p->xsize + XSIZEMAX);
  161.   for (s = p->xprev; s && (s->xpos > t); s = s->xprev)
  162.     set[s->id] = scnt;
  163.  
  164.   t = p->ypos + p->ysize + YSIZEMAX;
  165.   for (s = p->ynext; s && (s->ypos < t); s = s->ynext)
  166.     /* --- Is s->id member of set? --- */
  167.     if (set[s->id] == scnt) HandleCollision(p, s);
  168.   t = p->ypos - (p->ysize + YSIZEMAX);
  169.   for (s = p->yprev; s && (s->ypos > t); s = s->yprev)
  170.     if (set[s->id] == scnt) HandleCollision(p, s);
  171. }
  172.  
  173.  
  174. Sorry 'bout the long posting. I sorta got carried away ;)
  175.  
  176. --
  177. Bjorn Reese                      Email: breese@imada.ou.dk
  178. Odense University, Denmark       URL:   http://www.imada.ou.dk/~breese
  179.  
  180. "It's getting late in the game to show any pride or shame" - Marillion
  181.